package com.zhuanzhuan.hero.user.serverfilter;

import com.alibaba.fastjson.JSONObject;
import com.bj58.zhuanzhuan.zzentry.common.service.entity.ServiceHeaderEntity;
import com.bj58.zhuanzhuan.zzscf.extension.Active;
import com.bj58.zhuanzhuan.zzscf.extension.ServerFilter;
import com.bj58.zhuanzhuan.zzscf.invoke.Invocation;
import com.bj58.zhuanzhuan.zzscf.invoke.Result;
import com.bj58.zhuanzhuan.zzscf.invoke.ServerInvoker;
import com.zhuanzhuan.hero.user.enums.ExceptionMsgEnum;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.constraints.*;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;

@Active
public class ValidParamFilter implements ServerFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(ValidParamFilter.class);

    @Override
    public Result invoke(ServerInvoker<?> invoker, Invocation invocation) {
        LOGGER.info("ValidParamFilter before exec methodKey={}", invocation.getMethodKey());

        try {
            this.validParam(invocation);
        } catch (IllegalArgumentException e) {
            LOGGER.error("参数校验异常", e);
            Result result = new Result();
//            result.setException(e);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", ExceptionMsgEnum.PARAM_ERROR.getCode());
            jsonObject.put("errorMsg", e.getMessage());
            jsonObject.put("msg", e.getMessage());
            result.setResult(jsonObject);
            return result;
        }
        try {
            return invoker.invoke(invocation);
        } catch (BusinessException e) {
            LOGGER.error("执行业务异常", e);
            Result result = new Result();
            result.setException(e);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", e.getCode());
            jsonObject.put("errorMsg", e.getMessage());
            jsonObject.put("msg", e.getMessage());
            result.setResult(jsonObject);
            return result;
        } catch (Exception e) {
            LOGGER.error("执行未知异常", e);
            Result result = new Result();
            result.setException(e);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", -1);
            jsonObject.put("errorMsg", e.getMessage());
            jsonObject.put("msg", e.getMessage());
            result.setResult(jsonObject);
            return result;
        }
    }

    private void validParam(Invocation invocation) {
        Object[] arguments = invocation.getArguments();
        for (Object argument : arguments) {
            Class<?> clazz = argument.getClass();
            if (clazz.isPrimitive()) {
                continue;
            }

            if (clazz.equals(ServiceHeaderEntity.class)) {
                continue;
            }

            //是一个对象
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Class<?> type = field.getType();
                if (type.isPrimitive()) {
                    continue;
                }

                field.setAccessible(true);
                String fieldName = field.getName();
                Object fieldValue;
                try {
                    fieldValue = field.get(argument);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }

                NotNull notNullAnno = field.getAnnotation(NotNull.class);
                if (Objects.nonNull(notNullAnno) && Objects.isNull(fieldValue)) {
                    throw new IllegalArgumentException(notNullAnno.message());
                }

                //字符串不能为空
                NotBlank notBlankAnno = field.getAnnotation(NotBlank.class);
                if (Objects.nonNull(notNullAnno)) {
                    if (fieldValue instanceof String) {
                        if (StringUtils.isBlank((String)fieldValue)) {
                            throw new IllegalArgumentException(notBlankAnno.message());
                        }
                    }
                }

                //String,List,Map不可为空
                NotEmpty notEmptyAnno = field.getAnnotation(NotEmpty.class);
                if (Objects.nonNull(notEmptyAnno)) {
                    if (fieldValue instanceof String) {
                        if (StringUtils.isEmpty((String) fieldValue)) {
                            throw new IllegalArgumentException(notEmptyAnno.message());
                        }
                    } else if (fieldValue instanceof Collection) {
                        if (CollectionUtils.isEmpty((Collection) fieldValue)) {
                            throw new IllegalArgumentException(notEmptyAnno.message());
                        }
                    } else if (fieldValue instanceof Map) {
                        if (MapUtils.isEmpty((Map) fieldValue)) {
                            throw new IllegalArgumentException(notEmptyAnno.message());
                        }
                    }
                }

                //String正则校验
                Pattern patternAnno = field.getAnnotation(Pattern.class);
                if (Objects.nonNull(patternAnno)) {
                    if (!(fieldValue instanceof String)) {
                        throw new IllegalArgumentException("Pattern注解字段类型异常");
                    }
                    String strValue = (String)fieldValue;
                    if (StringUtils.isBlank(strValue) || !strValue.matches(patternAnno.regexp())) {
                        throw new IllegalArgumentException(patternAnno.message());
                    }
                }

                //String、List、Map的size最大最小值
                Size sizeAnno = field.getAnnotation(Size.class);
                if (Objects.nonNull(sizeAnno)) {
                    if (Objects.isNull(fieldValue)) {
                        throw new IllegalArgumentException(fieldName + "不可为null");
                    }
                    int min = sizeAnno.min();
                    int max = sizeAnno.max();
                    int valueSize;

                    if (fieldValue instanceof String) {
                        valueSize = ((String)fieldValue).length();
                    } else if (fieldValue instanceof Collection) {
                        Collection collectionValue = (Collection)fieldValue;
                        valueSize = collectionValue.size();
                    } else if (fieldValue instanceof Map) {
                        Map mapValue = (Map)fieldValue;
                        valueSize = mapValue.size();
                    } else {
                        throw new IllegalArgumentException("size注解字段类型错误");
                    }
                    if (valueSize < min || valueSize > max) {
                        throw new IllegalArgumentException(sizeAnno.message());
                    }
                }
            }
        }
    }
}
